package com.zmn.plat.business.impl.pilot;

import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.mcc.cas.model.LoginStaff;
import com.zmn.plat.business.interfaces.pilot.ChannelPriceBService;
import com.zmn.plat.business.interfaces.pilot.ChannelPriceLogBService;
import com.zmn.plat.business.interfaces.price.CommonBService;
import com.zmn.plat.common.constant.OnePriceConsts;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.dto.pilot.PilotEarnesPriceDRO;
import com.zmn.plat.common.enums.PilotConfigEnum;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.manager.dictionary.ProductDict;
import com.zmn.plat.model.entity.area.BaseArea;
import com.zmn.plat.model.entity.category.ServCategAndCategTwoQuery;
import com.zmn.plat.model.entity.pilot.*;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.product.ServProductQuery;
import com.zmn.plat.services.interfaces.area.BaseAreaService;
import com.zmn.plat.services.interfaces.pilot.ChannelPriceCategoryService;
import com.zmn.plat.services.interfaces.pilot.ChannelPriceCityService;
import com.zmn.plat.services.interfaces.pilot.ChannelPriceService;
import com.zmn.plat.services.interfaces.pilot.ServCityPriceService;
import com.zmn.plat.services.interfaces.product.ServProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述: 渠道试点复杂业务实现类
 *
 * @author guoqiao
 * @since 2021/6/25 15:32
 */
@Slf4j
@Service
public class ChannelPriceBServiceImpl implements ChannelPriceBService {

    @Resource
    ChannelPriceService channelPriceService;
    @Resource
    ChannelPriceBService channelPriceBService;
    @Resource
    ChannelPriceCityService channelPriceCityService;
    @Resource
    ChannelPriceLogBService logBService;
    @Resource
    BaseAreaService baseAreaService;
    @Resource
    ServCityPriceService servCityPriceService;
    @Resource
    ServProductService servProductService;
    @Resource
    CommonBService commonBService;

    @Override
    @Cacheable(cacheNames = "redis1h", key = "'pilot:categs:channelId:'+#p0+':cityId:'+#p1+':type:'+#p2+':servCategId:'+#p3+':categId:'+#p4", unless = "#result == null")
    public SupportPilotVO listPilotCategs(Integer channelId, Integer cityId, Integer type, Integer servCategId, Integer categId) {

        if (NumberUtil.isNullOrZero(channelId) || NumberUtil.isNullOrZero(cityId) || NumberUtil.isNullOrZero(type)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        // 查询区域
        BaseArea area = baseAreaService.findByKeyWithCache(cityId);
        if (Objects.isNull(area)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_AREA_NOT_EXIST);
        }
        SupportPilotVO vo = new SupportPilotVO();
        // 1.渠道层面
        List<ChannelPriceTO> channelPriceTOS;
        ChannelPriceTO query = new ChannelPriceTO();
        query.setChannelId(channelId);
        query.setType(type);
        query.setSupport(GlobalConsts.YES); // 不支持城市
        query.setProvinceId(area.getParentId());
        query.setCityId(cityId);
        query.setServCategId(servCategId);
        query.setCategTwoId(categId);
        channelPriceTOS = channelPriceService.listPriceTOByQuery(query);
        // 城市不支持
        if (!CollectionUtils.isEmpty(channelPriceTOS)) {
            return null;
        }
        query.setSupport(GlobalConsts.NO); // 支持城市
        channelPriceTOS = channelPriceService.listPriceTOByQuery(query);
        if (!CollectionUtils.isEmpty(channelPriceTOS)) {
            ChannelPriceTO channelPriceTO = channelPriceTOS.get(0);
            if (Objects.equals(type, OnePriceConsts.ONE_PRICE)) {
                // 设置支付方式
                vo.setPayType(channelPriceTO.getPayType());
                if (Objects.equals(channelPriceTO.getPayType(), GlobalConsts.NO) && Objects.equals(channelPriceTO.getDepositStatus(), GlobalConsts.YES)) {
                    // 设置定金
                    vo.setEarnestPrice(channelPriceTO.getDeposit());
                    if (Objects.equals(channelPriceTO.getDepositDeductionStatus(), GlobalConsts.YES)) {
                        vo.setDepositDeductionAmount(channelPriceTO.getDepositDeductionAmount()); // 设置定金抵扣
                    }
                }
            }
            List<ServCategAndCategTwoQuery> collect = channelPriceTOS
                    .stream()
                    .map(e -> new ServCategAndCategTwoQuery(e.getServCategId(), e.getCategOneId(), e.getCategTwoId())
                    ).collect(Collectors.toList());
            vo.setServCategIdList(collect);
            return vo;
        }

        // 2.城市层面
        // 未配置渠道维度，走城市维度
        ChannelPriceTO query2 = new ChannelPriceTO();
        query2.setType(type);
        query2.setProvinceId(area.getParentId());
        query2.setCityId(cityId);
        query2.setServCategId(servCategId);
        query2.setCategTwoId(categId);

        List<ChannelPriceTO> channelPriceTOS1 = servCityPriceService.listPriceTOByQuery(query2);
        if (!CollectionUtils.isEmpty(channelPriceTOS1)) {
            ChannelPriceTO channelPriceTO = channelPriceTOS1.get(0);
            if (Objects.equals(type, OnePriceConsts.ONE_PRICE)) {
                // 设置支付方式
                vo.setPayType(channelPriceTO.getPayType());
                if (Objects.equals(channelPriceTO.getPayType(), GlobalConsts.NO) && Objects.equals(channelPriceTO.getDepositStatus(), GlobalConsts.YES)) {
                    // 设置定金
                    vo.setEarnestPrice(channelPriceTO.getDeposit());
                    if (Objects.equals(channelPriceTO.getDepositDeductionStatus(), GlobalConsts.YES)) {
                        vo.setDepositDeductionAmount(channelPriceTO.getDepositDeductionAmount()); // 设置定金抵扣
                    }
                }
            }
            List<ServCategAndCategTwoQuery> collect = channelPriceTOS1
                    .stream()
                    .map(e -> new ServCategAndCategTwoQuery(e.getServCategId(), e.getCategOneId(), e.getCategTwoId())
                    ).collect(Collectors.toList());
            vo.setServCategIdList(collect);
            return vo;
        }
        return null;
    }


    @Override
    @Cacheable(cacheNames = "redis5m", key = "'pilot:open:categs:channelId:'+#p0+':cityId:'+#p1+':type:'+#p2", unless = "#result == null")
    public Boolean listPilotOpen(Integer channelId, Integer cityId, Integer type) {

        if (NumberUtil.isNullOrZero(channelId) || NumberUtil.isNullOrZero(cityId) || NumberUtil.isNullOrZero(type)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        // 查询区域
        BaseArea area = baseAreaService.findByKeyWithCache(cityId);
        if (Objects.isNull(area)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_AREA_NOT_EXIST);
        }
        // 1.渠道层面

        ChannelPriceTO query = new ChannelPriceTO();
        query.setChannelId(channelId);
        query.setType(type);
        List<ChannelPriceTO> channelPriceTOS = channelPriceService.listPriceTOByQuery(query);
        if (CollectionUtil.isNotNullOrEmpty(channelPriceTOS)){
            log.info("维修机器人试点校验渠道是否开通维修机器人：{}", Boolean.FALSE);
            return Boolean.FALSE;
        }
        // 2.城市层面
        // 未配置渠道维度，走城市维度
        ChannelPriceTO query2 = new ChannelPriceTO();
        query2.setType(type);

        List<ChannelPriceTO> channelPriceTOS1 = servCityPriceService.listPriceTOByQuery(query2);
        if (CollectionUtils.isEmpty(channelPriceTOS1)) {
            log.info("维修机器人试点校验城市是否开通维修机器人：{}", Boolean.TRUE);
            return Boolean.TRUE;
        }
        log.info("维修机器人试点校验城市是否开通维修机器人：{}", Boolean.FALSE);
        return Boolean.FALSE;
    }

    @Override
    public Boolean checkByChannelIdAndCityIdAndTypeAndCateg(Integer channelId, Integer cityId, Integer type, Integer servCategId, Integer categId) {

        SupportPilotVO supportPilotVO = channelPriceBService.listPilotCategs(channelId, cityId, type, servCategId, categId);
        if (Objects.nonNull(supportPilotVO) && !CollectionUtils.isEmpty(supportPilotVO.getServCategIdList())) {
            return true;
        }
        return false;
    }

    @Override
    public Boolean checkByChannelIdAndCityIdAndTypeAndProductId(Integer channelId, Integer cityId, Integer type, Integer productId, Integer showProductId) {

        if (NumberUtil.isNullOrZero(channelId) || NumberUtil.isNullOrZero(cityId) || NumberUtil.isNullOrZero(type) || NumberUtil.isNullOrZero(showProductId)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        // 查询前台产品
        ServProduct showProduct = servProductService.findByKeyWithCache(showProductId);
        if (Objects.isNull(showProduct)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SHOW_PRODUCT_NOT_EXIST);
        }
        // 校验是否开通分类
        Boolean isSupport = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId, type, showProduct.getServCategId(), showProduct.getCategId());
        // 不支持，直接返回false
        if (!isSupport) {
            return false;
        }
        // 还需通过产品校验计价器特性
        if (NumberUtil.isNotNullOrZero(productId)) {
            isSupport = commonBService.checkTariff(channelId, productId, ProductConsts.ERP_PRODUCT_TYPE, ProductConsts.BIZ_TYPE_C);
        } else {
            isSupport = commonBService.checkTariff(channelId, showProductId, ProductConsts.EC_PRODUCT_TYPE, ProductConsts.BIZ_TYPE_C);
        }
        return isSupport;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'pilot:checkTariffAndAdvance:channelId:'+#p0+':cityId:'+#p1+':showProductIdList:'+#p2", unless = "#result == null")
    public Map<Integer, Boolean> checkTariffAndAdvance(Integer channelId, Integer cityId, List<Integer> showProductIdList) {

        // 查询前台产品
        ServProductQuery query = new ServProductQuery();
        query.setProductIds(showProductIdList);

        List<ServProduct> products = servProductService.listPageByQuery(query);
        Map<Integer, Boolean> collect = new HashMap<>(products.size());
        if (CollectionUtils.isEmpty(products)) {
            return collect;
        }
        for (ServProduct product : products) {
            Integer productId = product.getProductId();
            // 校验是否支持计价器试点
            Boolean flag = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId,
                    PilotConfigEnum.FEE_METER.getType(), product.getServCategId(), product.getCategId());
            if (!flag) {
                collect.put(productId, false);
                continue;
            }
            // 校验是否支持预计价试点
            Boolean flag2 = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(channelId, cityId,
                    PilotConfigEnum.PAY_ADVANCE.getType(), product.getServCategId(), product.getCategId());
            if (!flag2) {
                collect.put(productId, false);
                continue;
            }
            // 查询计价器价格
            Map<Integer, Integer> traiffMap = commonBService.getTariff(channelId, Arrays.asList(productId),
                    ProductConsts.EC_PRODUCT_TYPE, ProductConsts.BIZ_TYPE_C, ProductDict.TRIFF_TYPE_TARIFF);
            if (!CollectionUtils.isEmpty(traiffMap)) {
                collect.put(productId, true);
                continue;
            }
            // 查询提前付价格
            Map<Integer, Integer> traiffMapAdv = commonBService.getTariff(channelId, Arrays.asList(productId),
                    ProductConsts.EC_PRODUCT_TYPE, ProductConsts.BIZ_TYPE_C, ProductDict.TRIFF_TYPE_ADVANCE);
            if (!CollectionUtils.isEmpty(traiffMapAdv)) {
                collect.put(productId, true);
                continue;
            }
            collect.put(productId, false);
        }
        return collect;
    }

    @Override
    public List<PilotEarnesPriceDRO> listPilotEarnesPrice(Integer channelId, Integer cityId, List<Integer> showProductIdList) {

        // 查询前台产品
        ServProductQuery query = new ServProductQuery();
        query.setProductIds(showProductIdList);
        List<PilotEarnesPriceDRO> droList = Optional.ofNullable(servProductService.listPageByQuery(query))
                .orElse(Collections.emptyList())
                .stream()
                .map(m -> {
                    SupportPilotVO supportPilotVO = channelPriceBService.listPilotCategs(channelId, cityId, OnePriceConsts.ONE_PRICE, m.getServCategId(), m.getCategId());
                    PilotEarnesPriceDRO dro = new PilotEarnesPriceDRO();
                    dro.setShowProductId(m.getProductId());
                    if (Objects.nonNull(supportPilotVO)) {
                        dro.setPayType(supportPilotVO.getPayType());
                        dro.setEarnestPrice(supportPilotVO.getEarnestPrice());
                        dro.setDepositDeductionAmount(supportPilotVO.getDepositDeductionAmount());
                    }
                    return dro;
                })
                .collect(Collectors.toList());
        return droList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer submitOnePrice(ChannelPriceVO channelPriceVO, LoginStaff staff) {

        try {
            ChannelPrice oldChannelPrice;
            List<ChannelPriceCity> oldPriceCity;
            Integer channelPriceId = channelPriceVO.getChannelPriceId();

            if (Objects.nonNull(channelPriceId)) {
                // 旧的执行城市配置
                oldChannelPrice = channelPriceService.findById(channelPriceId);
                // 数据库的执行配置数据
                ChannelPriceCityQuery query = new ChannelPriceCityQuery();
                query.setChannelPriceId(channelPriceId);
                oldPriceCity = channelPriceCityService.listByQuery(query);
                // 修改 先删除后新增
                channelPriceCityService.deleteByChannelPriceId(channelPriceId);
            } else {
                // 新的执行城市配置
                oldChannelPrice = new ChannelPrice();
                oldPriceCity = Collections.emptyList();
            }
            ChannelPrice newChannelOnePrice = this.addModifyChannelOnePrice(channelPriceVO, staff.getRealName());
            // 添加执行城市数据
            this.addChannelOnePriceCity(channelPriceVO, newChannelOnePrice.getChannelPriceId(), staff.getRealName());
            // 写入操作日志
            logBService.addChannelOnePriceLog(oldPriceCity, oldChannelPrice, newChannelOnePrice, staff.getRealName()
                    , staff.getStaffId(), channelPriceVO);

            return newChannelOnePrice.getChannelPriceId();
        } catch (Exception e) {
            log.error(" 提交执行配置信息失败,数据回滚:Exception{},msg{}", e, e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 描述: 新增渠道执行对应城市信息
     *
     * @param channelPriceVo 执行配置信息
     * @param updater        数据修改人
     * @param channelPriceId 渠道执行id
     * @author yangshuangping
     * @since 2021-6-28 09:46:39
     **/
    private void addChannelOnePriceCity(ChannelPriceVO channelPriceVo, Integer channelPriceId, String updater) {

        // 执行执行城市
        String channelCityIdStr = GlobalConsts.SPLITER_EMPTY;
        if (StringUtil.isNotBlank(channelPriceVo.getChannelPriceCityId())) {
            channelCityIdStr = channelPriceVo.getChannelPriceCityId();
        }
        // 不执行城市
        String channelBaseCityStr = GlobalConsts.SPLITER_EMPTY;
        if (StringUtil.isNotBlank(channelPriceVo.getChannelBaseCityId())) {
            channelBaseCityStr = channelPriceVo.getChannelBaseCityId();
        }
        ArrayList<ChannelPriceCity> collect = Lists.newArrayList();
        // 收集执行城市保存
        List<ChannelPriceCity> channelPriceCity = logBService.collectPriceCities(channelCityIdStr, channelPriceId
                , updater, OnePriceConsts.SUPPORT_CITY);

        collect.addAll(channelPriceCity);
        List<ChannelPriceCity> channelBaseCity = logBService.collectPriceCities(channelBaseCityStr, channelPriceId
                , updater, OnePriceConsts.NOT_SUPPORT_CITY);

        collect.addAll(channelBaseCity);

        if (!CollectionUtils.isEmpty(collect)) {
            channelPriceCityService.insertServBatchs(collect);
        }
    }


    /**
     * 描述: 新增渠道执行信息 如失败则抛出异常,数据回滚
     *
     * @param priceVO  执行配置信息
     * @param realName 数据修改人
     * @author yangshuangping
     * @since 2021-6-28 09:46:39
     **/
    private ChannelPrice addModifyChannelOnePrice(ChannelPriceVO priceVO, String realName) {

        ChannelPrice map = BeanMapper.map(priceVO, ChannelPrice.class);
        map.setUpdater(realName);
        //支付方式不为“下单必须支付”清空定金状态
        if (Objects.nonNull(priceVO.getChannelPriceId())) {
            map.setDepositStatus(!Objects.equals(map.getPayType(), GlobalConsts.NO) ? null : map.getDepositStatus());
            channelPriceService.updateByKey(map);
        } else {
            map.setCreater(realName);
            channelPriceService.insert(map);
        }
        return map;
    }

}
